<?php


namespace App\LayAdmin\Controllers;

use App\Exceptions\ExceptionApi;
use App\Http\Response\VideoResponse;
use App\LayAdmin\Components\Form;
use App\LayAdmin\Components\Table;
use App\LayAdmin\Components\TableData;
use App\LayAdmin\Components\TableFieldSearch;
use App\LayAdmin\Components\TableItemOperate;
use App\LayAdmin\Components\Template;
use App\Models\Image;
use App\Services\Logger;
use App\Services\Uri;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFMpeg;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Response;
use Illuminate\Http\Request;
use App\Models\Video;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use App\LayAdmin\Components\UploadMulti;

class VideosController extends BaseController
{

    /** 新手视频库 */
    public function weightList(Request $request):Response{
        $page = $request->input('page',null);
        $dataUrl = "/admin/videos/get-weight";
        if($page!==null){
            $dataUrl .= "?".$request->getQueryString();
        }
        $table = new Table($dataUrl);
        $this->tableFilter($table);
        $this->tableButtons($table, true);
        $table->addBtnPostToUrl('/admin/videos/batch-weight', '移到普通库');

        $this->tableCols($table, ['video_weight']);

        $this->tableItemOpt($table, true);

        return new Response($table->render());
    }

    /** 搜索过滤 */
    private function tableFilter(Table &$table){
        $time = (new TableFieldSearch('time_begin',''))->searchTimeInput(['placeholder'=>'选择开始时间']);
        $table->setSearchField($time);
        $time = (new TableFieldSearch('time_end',''))->searchTimeInput(['placeholder'=>'选择结束时间']);
        $table->setSearchField($time);
    }


    /**
     * 批量操作按钮组
     */
    private function tableButtons(Table $table, $weight=false){
        $uploadUrl = "/admin/videos/batch-upload";
        $weight && $uploadUrl = $uploadUrl."?weight=1";
        $table->addBtnOpenByUrl($uploadUrl, '批量上传',['layui-btn layui-btn-normal']); // $table->addBtnRedirectToUrl($uploadUrl, '批量上传');
        $table->addBtnPostToUrl('/admin/videos/batch-delete', '批量删除',['layui-btn-danger']);
        $table->addBtnPostToUrl('/admin/videos/batch-recommend', '批量推荐');
        $table->addBtnPostToUrl('/admin/videos/batch-cancel-recommend', '取消推荐',['layui-btn-primary']);

    }

    /**
     * 数据操作列
     */
    private function tableItemOpt(Table $table, $weight=false){
        $table->itemOperate(function (TableItemOperate $operate)use($weight){
            $operate->setBtnGet("\"/admin/video?id=\"+data.id", '播放');
            $editUrl = $weight ? "\"/admin/videos/edit-weight?id=\"+data.id" : "\"/admin/videos/edit?id=\"+data.id";
            $operate->setEditBtn($editUrl);
            $delUrl = "\"/admin/videos/delete\"";
            $operate->setDeleteBtn($delUrl);
        });
    }

    /**
     * 数据表格列
     */
    private function tableCols(Table &$table, $extFields=[]){
        $table->checkbox();
        // ,{field:'author_img', title: '用户头像', width:120}
        // ,{field:'image', title: '短视频封面', width:120}
        $table->field('id', 'ID')->setWidth(80)->setSort();
        $table->field('title', '标题')->setWidth(788)->search();
        in_array('video_weight', $extFields) && $table->field('video_weight', '权重')->setWidth(80)->setSort();
        $table->field('is_recommend', '精选')->setWidth(60)->search()->searchSelectInput([''=>'全部',0=>'否',1=>'是']);
        $table->field('likes_num', '点赞')->setWidth(80)->setSort();
        $table->field('review_num', '评论')->setWidth(80)->setSort();
        $table->field('created_at', '上传日期')->setWidth(160)->setSort();
    }

    /** 视频列表 */
    public function index(Request $request) :Response {
        $page = $request->input('page',null);
        $dataUrl = "/admin/videos/get";
        if($page!==null){
            $dataUrl .= "?".$request->getQueryString();
        }
        $table = new Table($dataUrl);

        $this->tableFilter($table);
        $this->tableButtons($table);
        $table->addBtnPostToUrl('/admin/videos/batch-weight?weight=1000', '移到新手库');

        $this->tableCols($table);

        $this->tableItemOpt($table);

        return new Response($table->render());
    }

    protected function getModel(Request $request):Video{
        $id = $request->input('id');
        $data = $request->input('data');
        if($id==null && isset($data['id'])){
            $id = $data['id'];
        }
        $model = Video::query()->where('id', '=', $id)->first(); // Video::find($id);
        if(!$model){
            throw new ExceptionApi('视频不存在');
        }
        return $model;
    }

    public function delete(Request $request):Response{
        $model = $this->getModel($request);
        $msg = '删除失败';
        if($model->delete()){
            $msg = '删除成功';
        }
        return new Response(['msg'=>$msg, 'code'=>200]);
    }

    public function openVideo(Request $request):Response{
        $model = $this->getModel($request);
        $src = Uri::createVideoUrl($model->path);
        $html = <<<HTML
<div class="layuimini-container layuimini-page-anim">
    <div class="layuimini-main">
        <video width="360px" height="720px"  controls="controls" autobuffer="autobuffer"  autoplay="autoplay" loop="loop">
        <source src="{$src}" type="video/mp4"></source>
        </video>
    </div>
</div>
HTML;
        return new Response($html);
    }

    protected function batchOperate(Request $request, \Closure $closure):Response{
        $ids = $request->input('ids');
        if(empty($ids)){
            throw new ExceptionApi('没有要操作的数据');
        }
        $query = Video::query()->whereIn('id', $ids);
        $closure($query);
        return new Response(['data'=>null, 'msg'=>'操作成功','code'=>200]);
    }

    public function batchDelete(Request $request):Response{
        return $this->batchOperate($request, function (Builder $query){
            $query->delete();
        });
    }

    public function batchRecommend(Request $request):Response{
        return $this->batchOperate($request, function (Builder $query){
            $query->update(['is_recommend'=>1]);
        });
    }

    public function batchCancelRecommend(Request $request):Response{
        return $this->batchOperate($request, function (Builder $query){
            $query->update(['is_recommend'=>0]);
        });
    }

    /**
     * 批量设置权重
     * /admin/videos/batch-weight
     */
    public function batchWeight(Request $request):Response{
        $weight = $request->input('weight',0);
        return $this->batchOperate($request, function (Builder $query)use($weight){
            $query->update(['weight'=>$weight]);
        });
    }

    public function editWeight(Request $request):Response{
        $model = $this->getModel($request);
        $form = new Form("/admin/videos/edit-weight");
        $form->field('id', $model->id)->hide();
        $form->field('title', $model->title)->label('标题')->textInput();
        $form->field('weight', $model->weight)->label('排序权重')->textInput();
        $form->submit();
        return new Response($form->render());
    }

    public function edit(Request $request):Response{
        $model = $this->getModel($request);
        $form = new Form("/admin/videos/edit");
        $form->field('id', $model->id)->hide();
        $form->field('title', $model->title)->label('标题')->textInput();
        $form->field('is_recommend', $model->is_recommend)->label('是否推荐')->radioList([1=>'是',0=>'否']);
        $form->submit();
        return new Response($form->render());
    }

    public function update(Request $request):Response{
        $model = $this->getModel($request);
        $data = $request->input('data');
        $model->title = $data['title'];
        $model->is_recommend = $data['is_recommend'];
        if($model->save()){
            return $this->successApi();
        }
        throw new ExceptionApi('更新失败');
    }

    public function updateWeight(Request $request):Response{
        $model = $this->getModel($request);
        $data = $request->input('data');
        $model->title = $data['title'];
        $model->weight = $data['weight'];
        if($model->save()){
            return $this->successApi();
        }
        throw new ExceptionApi('更新失败');
    }

    /**
     * 批量上传视频页面
     */
    public function batchUpload(Request $request):Response{
        $weight = $request->input('weight');

        $uploadMulti = new UploadMulti('/admin/videos/upload', UploadMulti::ACCEPT_VIDEO);
        $form = new Form("");
        if($weight){
            $form->field('weight', 1000)->textInput()->label('排序权重');
        }else{
            $form->field('is_recommend',0)
                ->radioList([1=>'是',0=>'否'])
                ->label('是否精选');
        }
        $uploadMulti->setForm($form);

        $html = Template::getInstance()->render('batch_upload.php', compact('uploadMulti'));
        return new Response($html);
    }

    /** 获取视频列表数据 */
    protected function getData(Request $request, $weight=false):Response{
        $page = $request->input('page',1);
        $limit = $request->input('limit',30);
        if($weight){
            $query = Video::getQuery()->where("weight", ">",0)->orderByDesc('weight');
        }else{
            $query = Video::getQuery()->where("weight", "=",0);
        }

        $searchParams = $request->input('searchParams');
        if($searchParams){
            $filter = json_decode($searchParams, true);
            Video::filterData($query, $filter);
        }

        $videos = $query->orderByDesc('id')->paginate($limit, ["*"], 'page', $page);

        $items = $videos->items();
        foreach ($items as &$item){
            $item = VideoResponse::toArray($item);
            $item['is_recommend'] = $item['is_recommend']==0 ? '否' : '是';
            $item['image'] = "<img src=\"{$item['image']}\">";
            $item['author_img'] = "<img src=\"{$item['author_img']}\">";
        }
        $total = $videos->total();
        $response = (new TableData($items, $total))->toArray(); // ['code'=>0,'count'=>$total,'msg'=>'','data'=>$items];
        return new Response($response);
    }

    /**
     * 获取视频列表数据
     */
    public function getTableData(Request $request):Response{
        return $this->getData($request,false);
    }

    /** 获取视频列表数据 */
    public function getTableDataWeight(Request $request):Response{
        return $this->getData($request,true);
    }



    /**
     * 处理上传视频。 提取文件名做为标题。截取首帧作为封面图。
     */
    public function upload(Request $request):Response{
        $video = $request->file('file');
        $is_recommend = $request->input('is_recommend',0);
        $weight = $request->input('weight',0);

        $originName = $video->getClientOriginalName();
        $originExt = $video->getClientOriginalExtension();
        $filename = date('Y_m_d_H_i_s_').Str::random(8); // md5($originName);
        $saveName = $filename;
        if($originExt){
            $saveName = $filename.".{$originExt}";
        }

        $nameInfo = explode('.', $originName);
        $title = $originName;
        if(count($nameInfo)>0){
            $title = $nameInfo[0];
        }

        $model = Video::query()->where(['title'=>$title])->first();
        if($model){
            throw new ExceptionApi('文件已上传过');
        }

        $path = $video->storeAs('videos', $saveName, 'uploads');

        // 截取视频首帧图片
        $imageFilename = $filename . ".jpg";
        $imagePath = "videos/".$imageFilename;
        $imageFullPath = Uri::getFullPath($imagePath);
        $videoFullPath = Uri::getFullPath($path);

        $ffmpeg = FFMpeg::create();
        $ffmpegVideo = $ffmpeg->open($videoFullPath);
        $ffmpegVideo->frame(TimeCode::fromSeconds(0))->save($imageFullPath);
//        $cmd = "ffmpeg -i {$videoFullPath} -ss 00:00:00 -f mjpeg -y $imageFullPath"; // -s 352x240
//        shell_exec($cmd);

        try{
            DB::beginTransaction();
            $model = new Video();
            $model->user_id = 1;
            $model->title = $title;
            $model->path = $path;
            $model->likes_num = 0;
            $model->review_num = 0;
            $model->is_recommend = $is_recommend;
            $model->weight = $weight;
            $model->save();
            $imageModel = new Image();
            $imageModel->addFromVideo($model, $imagePath);
            DB::commit();
        }catch (\Exception $exception){
            Logger::debug("===短视频上传失败===".$exception->getMessage());
        }

        $url = Uri::createVideoUrl($path);
        return new Response(['code'=>0,'msg'=>'success','data'=>['src'=>$url]]);
    }

}
